\chapter{Primitive operations}

\section{Purpose}

Primitive operations (or primops for short) are similar to
\commonlisp{} special operators in that the compiler handles them
specially.  They are different from \commonlisp{} special operators in
that a primop does not necessarily have an evaluation rule that is
different from that of a function call.

Generally speaking, primops should not be used directly in application
code.  Instead, they are used in system code for implementing certain
basic \commonlisp{} function.  So, for example, the \texttt{car}
primop would typically be used only in the code for the \commonlisp{}
function \texttt{car}.  That function would then be inlined by the
compiler, so that the resulting AST and ultimately the resulting HIR
instruction that the \texttt{car} primop translates to will be present
also in application code.

Frequently, the need for a primop arises because some HIR instruction
is needed.  Take, for example, the HIR instruction named
\texttt{eq-instruction} for comparing two pointer values for equality.
The existence of that instruction requires an AST doing the same
thing, and it is called \texttt{eq-ast}.  When compiled to HIR, the
\texttt{eq-ast} generates the an \texttt{eq-instruction}.  Finally, in
order to produce the source for the \commonlisp{} function
\texttt{eq}, it must be possible to produce the \texttt{eq-ast} from
some \commonlisp{} code, which is why the \texttt{eq} primop is
needed.

\section{Package}

All primitive operations have names that are symbols in the package
named \texttt{cleavir-primop}.  This package contains only those
symbols that name the primitive operations.  There is no code directly
associated with the primitive operations.  Instead, the code for
translating primitive operations to abstract syntax trees
\seechap{chap-abstract-syntax-tree} is in the form of methods on the
function \texttt{cleavir-cst-to-ast:convert-special}.

\section{Existing primitive operations}

\def\Defprimop #1 #2 {\Dodocf {#1} {#2} {Primitive operation}}

\Defprimop{eq} {object1 object2}

This primitive operation has the same semantics as the \commonlisp{}
function \texttt{eq}.  Its main purpose is
for defining the code for that \commonlisp{} function.  Typically the
\commonlisp{} \texttt{eq} function will be declared \texttt{inline} so
that the abstract syntax tree and HIR instruction resulting from this
primop will eventually end up in the compiled code of many
applications.

\Defprimop{typeq} {object type-specifier}

This primitive operation is similar to the \commonlisp{} function
\texttt{typep}.  It differs from the \commonlisp{} function in that it
does not evaluate its second argument.
Also, it does not take an optional environment argument%
\footnote{We may have to add an environment argument to
  \texttt{typeq}.  Alternatively we may have to specify that it only
  takes certain types that do not depend on the environment.}
like \texttt{typep} does.

The implementation may have a compiler macro on the function
\texttt{typep} so that it turns into \texttt{typeq} when the second
argument is a constant.  The \texttt{typeq} primitive operation can
also be used in the implementation of certain system functions that
need to check for constant types.

The \texttt{typeq} generates a \texttt{typeq} AST and ultimately a
\texttt{typeq} HIR instruction.  This instruction is used by the type
inferencer \seesec{sec-optimizations-type-inference} to infer
different types in different successor branches.

\Defprimop{car} {cons}

This primitive operation is typically used in the implementation of
the \commonlisp{} function \texttt{car}.  The main difference between
this primitive operation and the \commonlisp{} function is that the
primitive operation requires its argument to evaluate to a
\texttt{cons}.  For that reason, if used to implement the
\commonlisp{} function \texttt{car}, this primitive operation should
be preceded by a test (using the primitive operation \texttt{typeq})
to verify that the argument is a \texttt{cons}.  A typical
implementation of the \texttt{car} function might look like this:

\begin{verbatim}
  (defun car (object)
    (if (cleavir-primop:typeq object cons)
        (cleavir-primop:car object)
        (if (cleavir-primop:typeq object null)
            nil
            (error 'type-error
                   :datum object
                   :expected-type '(or cons null)))))
\end{verbatim}

The \commonlisp{} \texttt{car} function will typically be declared
\texttt{inline}, allowing the type inferencer
\seesec{sec-optimizations-type-inference} to use the \texttt{typeq}
primitive operation to remove redundant type checks.

\Defprimop{cdr} {cons}

This primitive operation is typically used in the implementation of
the \commonlisp{} function \texttt{cdr}.  The main difference between
this primitive operation and the \commonlisp{} function is that the
primitive operation requires its argument to evaluate to a
\texttt{cons}.  For that reason, if used to implement the
\commonlisp{} function \texttt{cdr}, this primitive operation should
be preceded by a test (using the primitive operation \texttt{typeq})
to verify that the argument is a \texttt{cons}.  A typical
implementation of the \texttt{cdr} function might look like this:

\begin{verbatim}
  (defun cdr (object)
    (if (cleavir-primop:typeq object cons)
        (cleavir-primop:cdr object)
        (if (cleavir-primop:typeq object null)
            nil
            (error 'type-error
                   :datum object
                   :expected-type '(or cons null)))))
\end{verbatim}

The \commonlisp{} \texttt{cdr} function will typically be declared
\texttt{inline}, allowing the type inferencer
\seesec{sec-optimizations-type-inference} to use the \texttt{typeq}
primitive operation to remove redundant type checks.

\Defprimop{rplaca} {cons object}

This primitive operation is typically used in the implementation of
the \commonlisp{} function \texttt{rplaca}.  It requires its first
argument to be a \texttt{cons}.  For that reason, if used to implement
the \commonlisp{} function \texttt{rplaca}, this primitive operation
should be preceded by a test (using the primitive operation
\texttt{typeq}) to verify that the argument is a \texttt{cons}.  A
typical implementation of the \texttt{rplaca} function might look like
this:

\begin{verbatim}
  (defun rplaca (cons object)
    (if (cleavir-primop:typeq object cons)
        (cleavir-primop:rplaca cons object)
        (error 'type-error
               :datum object
               :expected-type 'cons)))
\end{verbatim}

\Defprimop{rplacd} {cons object}

This primitive operation is typically used in the implementation of
the \commonlisp{} function \texttt{rplacd}.  It requires its first
argument to be a \texttt{cons}.  For that reason, if used to implement
the \commonlisp{} function \texttt{rplacd}, this primitive operation
should be preceded by a test (using the primitive operation
\texttt{typeq}) to verify that the argument is a \texttt{cons}.  A
typical implementation of the \texttt{rplacd} function might look like
this:

\begin{verbatim}
  (defun rplacd (cons object)
    (if (cleavir-primop:typeq object cons)
        (cleavir-primop:rplacd cons object)
        (error 'type-error
               :datum object
               :expected-type 'cons)))
\end{verbatim}

\Defprimop{let-uninitialized} {(\rest vars) \body forms}

This primitive operation is used for creating uninitialized lexical
variables.  It takes at least one argument which must be a list of
symbols representing these lexical variables.  The remaining arguments
are arbitrary forms that may refer to the variables in the list.  Each
variable must be assigned to before it is used.

This primitive operation is used in combination with other primitive
operations such as \texttt{fixnum-add} and \texttt{fixnum-sub} that
must appear as the \emph{test-form} form in an \texttt{if} form, but
that also produce output.

\Defprimop{fixnum-add} {arg1 arg2 var}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{+}.  It takes three arguments.  The
first two arguments can be arbitrary expressions that must both
evaluate to \texttt{fixnum}s.   The third argument is a symbol.  It is
not evaluated and it must be the name of an existing lexical
variable.  This variable is typically created by the primitive
operation \texttt{let-uninitialized}.

The \texttt{fixnum-add} operation can only appear as the
\emph{test-form} in the special form \texttt{if}.

This primitive operation adds the two fixnum values to produce a
\emph{result} $r$ that is stored in the variable represented by the
third argument.  The result is always a fixnum.  If the addition
produces a number that can be represented as a fixnum, then the $r$
is that number.  If the addition produces a number that can \emph{not}
be represented as a fixnum, then there are two cases:

\begin{enumerate}
\item If $r$ is \emph{negative}, then the addition yielded the number
  $2^n + r$, where $n$ is the number of bits in a word.
\item If $r$ is \emph{non-negative}, then the addition yielded the
  number $2^n - r$, where $n$ is the number of bits in a word.
\end{enumerate}

In addition to producing a result in the variable, the \emph{value} of
the \texttt{fixnum-add} form is a Boolean value that is used to
determine the which branch of the \texttt{if} form is evaluated next.
If the addition produced a number that can be represented as a fixnum,
then the Boolean value is \emph{true}.  Otherwise it is \emph{false}.

\Defprimop{fixnum-sub} {arg1 arg2 var}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{-}.  It takes three arguments.  The
first two arguments can be arbitrary expressions that must both
evaluate to \texttt{fixnum}s.   The third argument is a symbol.  It is
not evaluated and it must be the name of an existing lexical
variable.  This variable is typically created by the primitive
operation \texttt{let-uninitialized}.

The \texttt{fixnum-sub} operation can only appear as the
\emph{test-form} in the special form \texttt{if}.

This primitive operation subtracts the two fixnum values to produce a
\emph{result} $r$ that is stored in the variable represented by the
third argument.  The result is always a fixnum.  If the subtraction
produces a number that can be represented as a fixnum, then the $r$ is
that number.  If the subtraction produces a number that can \emph{not}
be represented as a fixnum, then there are two cases:

\begin{enumerate}
\item If $r$ is \emph{negative}, then the subtraction yielded the
  number $2^n + r$, where $n$ is the number of bits in a word.
\item If $r$ is \emph{non-negative}, then the subtraction yielded the
  number $2^n - r$, where $n$ is the number of bits in a word.
\end{enumerate}

In addition to producing a result in the variable, the \emph{value}
of the \texttt{fixnum-sub} form is a Boolean value that is used to
determine the which branch of the \texttt{if} form is evaluated next.
If the subtraction produced a number that can be represented as a
fixnum, then the Boolean value is \emph{true}.  Otherwise it is
\emph{false}.

\Defprimop{fixnum-less} {}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{<}.  It takes two arguments, both forms
that must evaluate to fixnums.  It can only appear as the
\emph{test-form} in the special form \texttt{if}.

If the first argument is strictly less than the second argument, then
the \emph{then} branch of the \texttt{if} form is evaluated.
Otherwise, the \emph{else} branch of the \texttt{if} form is
evaluated.

\Defprimop{fixnum-not-greater} {}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{<=}.  It takes two arguments, both
forms that must evaluate to fixnums.  It can only appear as the
\emph{test-form} in the special form \texttt{if}.

If the first argument is less than or equal to the second argument,
then the \emph{then} branch of the \texttt{if} form is evaluated.
Otherwise, the \emph{else} branch of the \texttt{if} form is
evaluated.

\Defprimop{fixnum-greater} {}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{>}.  It takes two arguments, both
forms that must evaluate to fixnums.  It can only appear as the
\emph{test-form} in the special form \texttt{if}.

If the first argument is strictly greater than the second argument,
then the \emph{then} branch of the \texttt{if} form is evaluated.
Otherwise, the \emph{else} branch of the \texttt{if} form is
evaluated.

\Defprimop{fixnum-not-less} {}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{>=}.  It takes two arguments, both
forms that must evaluate to fixnums.  It can only appear as the
\emph{test-form} in the special form \texttt{if}.

If the first argument is greater than or equal to the second argument,
then the \emph{then} branch of the \texttt{if} form is evaluated.
Otherwise, the \emph{else} branch of the \texttt{if} form is
evaluated.

\Defprimop{fixnum-equal} {}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{=}.  It takes two arguments, both
forms that must evaluate to fixnums.  It can only appear as the
\emph{test-form} in the special form \texttt{if}.

If the first argument is equal to the second argument,
then the \emph{then} branch of the \texttt{if} form is evaluated.
Otherwise, the \emph{else} branch of the \texttt{if} form is
evaluated.

\Defprimop{float-add} {}

\def\ittakesthree{It takes three arguments.  The
first one is a floating-point type and it is not evaluated.  The
second and the third arguments are both forms that must evaluate to
floats of the type indicated by the first argument.}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{+}.  \ittakesthree{}

The value of a form with this operator is a float of the type
indicated by the first argument, representing the sum of the second
and the third arguments.

If the result of the operation is greater than the value of the
constant variable that contains the most positive floating-point value
of the type indicated by the first argument, then an error of type
\texttt{floating-point-overflow} is signaled.

If the result of the operation is less than the value of the constant
variable that contains the most negative floating-point value of the
type indicated by the first argument, then an error of type
\texttt{floating-point-underflow} is signaled.

\Defprimop{float-sub} {}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{-}.  \ittakesthree{}

\Defprimop{float-mul} {}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{*}.  \ittakesthree{}

\Defprimop{float-div} {}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{/}.  \ittakesthree{}

\Defprimop{float-less} {}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{<}.  \ittakesthree{}
It can only appear as the \emph{test-form} in the special form
\texttt{if}.

If the first argument is strictly less than the second argument, then
the \emph{then} branch of the \texttt{if} form is evaluated.
Otherwise, the \emph{else} branch of the \texttt{if} form is
evaluated.

\Defprimop{float-not-greater} {}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{<=}.  \ittakesthree{}
It can only appear as the \emph{test-form} in the special form
\texttt{if}.

If the first argument is less than or equal to the second argument,
then the \emph{then} branch of the \texttt{if} form is evaluated.
Otherwise, the \emph{else} branch of the \texttt{if} form is
evaluated.

\Defprimop{float-greater} {}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{>}.  \ittakesthree{} It can only appear
as the \emph{test-form} in the special form \texttt{if}.

If the first argument is strictly greater than the second argument,
then the \emph{then} branch of the \texttt{if} form is evaluated.
Otherwise, the \emph{else} branch of the \texttt{if} form is
evaluated.

\Defprimop{float-not-less} {}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{>=}.  \ittakesthree{} It can only appear
as the \emph{test-form} in the special form \texttt{if}.

If the first argument is greater than or equal to the second argument,
then the \emph{then} branch of the \texttt{if} form is evaluated.
Otherwise, the \emph{else} branch of the \texttt{if} form is
evaluated.

\Defprimop{float-equal} {}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{=}.  \ittakesthree{} It can only appear
as the \emph{test-form} in the special form \texttt{if}.

If the first argument is numerically equal to the second argument,
then the \emph{then} branch of the \texttt{if} form is evaluated.
Otherwise, the \emph{else} branch of the \texttt{if} form is
evaluated.

\Defprimop{float-sin} {}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{sin}.  It takes a single argument which
much be a short float.

The value of a form with this operation is a short float representing
the \emph{sine} of the argument.

This operation always succeeds, since the value of the \texttt{sin}
function is always in the range allowed by short floats.

\Defprimop{float-cos} {}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{cos}.  It takes a single argument which
much be a short float.

The value of a form with this operation is a short float representing
the \emph{cosine} of the argument.

This operation always succeeds, since the value of the \texttt{cos}
function is always in the range allowed by short floats.

\Defprimop{float-sqrt} {}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{sqrt}.  It takes a single argument which
much be a non-negative short float.

The value of a form with this operation is a short float representing
the \emph{square root} of the argument.

This operation always succeeds, since the value of the \texttt{SQRT}
function is closer to $1$ than its argument.

\Defprimop{nook-read} {}

This primitive operation is used in the implementation of the MOP
function \texttt{standard-instance-access}.  It takes two arguments.
The first argument is a form that must evaluate to a standard
instance%
\footnote{Implementations are free to use this operation to access
  other objects as well, provided that those objects have the same
  memory layout as standard instances.}
The second argument is a form that must evaluate to a fixnum.

This operation returns the contents of the nook at the offset
indicated by the second argument in the instance indicated by the
first argument.

\Defprimop{nook-write} {}

This primitive operation is used in the implementation of the MOP
function \texttt{(setf standard-instance-access)}.  It takes three
arguments.  The first argument is a form that must evaluate to a
standard instance%
\footnote{As with the primitive operation NOOK-READ, implementations
  are free to use this primitive operation for other purposes as
  well.}
The second argument is a form that must evaluate to a fixnum and that
indicates the nook number to be written.  The third argument is a form
that evaluates to the object that will be written to the nook.

Forms using this primitive operation must occur in a context that does
not require a value, such as in a \texttt{progn} other than as the
last form.

\Defprimop{aref} {array index element-type simple-p boxed-p}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{aref}.  It takes five arguments.  The
\textit{array} argument is a form that must evaluate to an array.  The
\textit{index} argument is a form that must evaluate to fixnum
representing a valid row-major index of the array.  The remaining
arguments are not evaluated.  The \textit{element-type} argument is
the element type of the array.  The \textit{simple-p} argument
argument is a Boolean indicating whether the array is simple.  The
\textit{boxed-p} argument is a Boolean indicating whether the elements
of the array are boxed.

This primitive operation returns the object at \textit{index} in
\textit{array}.

\Defprimop{aset} {array index object element-type simple-p boxed-p}

This primitive operation is used in the implementation of the
\commonlisp{} function \texttt{(setf aref)}.  The \textit{array}
argument is a form that must evaluate to an array.  The \texttt{index}
argument is a form that must evaluate to a fixnum.  It represents a
valid row-major index into \textit{array}.  The remaining arguments
are not evaluated.  The \textit{element-type} argument is the element
type of the array.  The \textit{simple-p} argument argument is a
Boolean indicating whether the array is simple.  The \textit{boxed-p}
argument is a Boolean indicating whether the elements of the array are
boxed.

This primitive operation stores \textit{object} at \textit{index} in
\textit{array}.

Forms using this primitive operation must occur in a context that does
not require a value, such as in a \texttt{progn} other than as the
last form.

\Defprimop{funcall} {function \rest arguments}

This primitive operation is similar to the function \texttt{cl:funcall}.
The difference is that the primop does not allow a function name as
the value of its first argument. It must be a function.

In order to inline \texttt{cl:funcall}, a possible strategy would
be to define a compiler macro on that function that expands to a
form that turns the first argument into a function if it is not
already, and then calls this primitive operation.

\Defprimop{values} {\rest arguments}

This primitive operation is similar to the function \texttt{cl:values},
differing only in that it is a primitive operation and not a function.
It can be used to inline calls to \texttt{cl:values} with a fixed
number of arguments, for example with a compiler macro:

\begin{verbatim}
(define-compiler-macro (&rest arguments)
  `(cleavir-primop:values ,@values))
\end{verbatim}
